/**
 * 
 */
package edu.umd.clip.lm.factors;

import java.nio.charset.Charset;
import java.util.regex.*;

/**
 * @author Denis Filimonov <den@cs.umd.edu>
 *
 */
public class CaseInfoExtended implements WordToOvertFactorInterface {
	public static final String allCaps = "ALLCAPS";
	public static final String capitalized = "Cap";
	public static final String abbr = "Abbr.";
	public static final String nonWord = "non-word";
	public static final String regular = "reg";
	public static final String number = "num";
	public static final String datetime = "datetime";
	public static final String punct = "punct";
	public static final String currency = "currency";
	public static final String fw = "fw";
	public static final String hyphenated = "hyphenated";
	public static final String ordinal = "ordinal";
	public static final String wordnum = "wordnum";
	
	private static final Pattern punct_re = Pattern.compile("^(?:[?!,\"`:;(){}\\[\\]-]+|``|\\.+|''|--+|-[LR][CSR]B-)$");
	private static final Pattern currency_re = Pattern.compile("^(?:[a-z]*\\$|#)$", Pattern.CASE_INSENSITIVE);
	private static final Pattern ordinal_re = Pattern.compile(".*(?:1st|2nd|3rd|[04-9]th)$", Pattern.CASE_INSENSITIVE);
	private static final Pattern wordnum_re = Pattern.compile("^[a-z]*[0-9][a-z0-9]*$", Pattern.CASE_INSENSITIVE);
	
	private static final Pattern cap_re = Pattern.compile("^[A-Z]");
	private static final Pattern nonWord_re = Pattern.compile("^[^a-zA-Z]+$");
	private static final Pattern num_re = Pattern.compile("^-?\\d[\\d.,/-]*(?:[eE]-?\\d+)?$");
	private static final Pattern datetime_re = Pattern.compile("^(?:\\d+(?:(?:[:/])\\d+){1,2}|'\\d{2,4}s?)$");
	private static final Pattern regular_re = Pattern.compile("^(?:'?[a-z])*'?$"); // includes 'n', 's, and '
	
	private static final Charset utf8 = Charset.forName("UTF-8");
	
	public CaseInfoExtended() {
	}
	
	/* (non-Javadoc)
	 * @see edu.umd.clip.lm.factors.WordToOvertFactorInterface#wordToOvertFactor(java.lang.String)
	 */
	@Override
	public String wordToOvertFactor(String word) {
		{
			byte bytes[];
			bytes = word.getBytes(utf8);
			for(byte b : bytes) {
				// if non-ascii, return foreign-word
				if (b < 0) return fw;
			}
		}
		if (regular_re.matcher(word).matches()) return regular;
		
		if (punct_re.matcher(word).matches()) return punct;
		if (currency_re.matcher(word).matches()) return currency;
		if (ordinal_re.matcher(word).matches()) return ordinal;
		if (num_re.matcher(word).matches()) return number;
		if (datetime_re.matcher(word).matches()) return datetime;
		if (wordnum_re.matcher(word).matches()) return wordnum;

		if (cap_re.matcher(word).find()) {
			if (word.endsWith(".")) return abbr;
			if (word.equals(word.toUpperCase())) return allCaps;
			return capitalized;
		}

		if (word.indexOf("-") != -1) return hyphenated;
		
		if (nonWord_re.matcher(word).matches()) return nonWord;
		// anything else (hopefully nothing)
		return regular;
	}

}
